package com.huawei.translate.api;

import com.huawei.translate.model.Application;
import com.huawei.translate.model.Renter;
import com.huawei.translate.notification.service.EmailTemplateType;
import com.huawei.translate.notification.service.NotificationService;
import com.huawei.translate.persistence.ApplicationRepository;
import com.huawei.translate.persistence.RenterRepository;
import com.huawei.translate.vo.application.ApplicationDto;
import com.huawei.translate.vo.application.ApplicationRequest;
import com.huawei.translate.vo.application.ApplicationsDto;
import com.huawei.translate.vo.application.UpdateApplicationRequest;
import com.huawei.translate.vo.user.RenterDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

@RestController
@RequestMapping("/api/applications")
@Api(value = "application API", description = "applicant api")
public class ApplicationApi {

    @Autowired
    private ApplicationRepository applicationRepository;

    @Autowired
    private RenterRepository renterRepository;

    @Autowired
    private NotificationService notificationService;


    @ApiOperation(value = "applicate", httpMethod = "POST")
    @RequestMapping(method = POST)
    public ResponseEntity<RenterDto> create(@RequestBody ApplicationRequest request) {
        Application application = request.toApplication();
        applicationRepository.save(application);
        notificationService.send(EmailTemplateType.ApplicationSubmission, application);
        return new ResponseEntity(HttpStatus.CREATED);
    }

    @ApiOperation(value = "application", httpMethod = "GET")
    @RequestMapping(method = GET)
    public ResponseEntity<ApplicationsDto> all() {

        List<ApplicationDto> dtoList = new ArrayList<>();

        applicationRepository.findAll(new Sort(Sort.Direction.DESC, "createdAt"))
                .stream()
                .forEach(application -> dtoList.add(application.toDto()));

        ApplicationsDto applicationsDto = new ApplicationsDto();

        applicationsDto.setList(dtoList);

        return new ResponseEntity(applicationsDto, HttpStatus.OK);
    }

    @ApiOperation(value = "application", httpMethod = "GET")
    @RequestMapping(value = "/{id}", method = GET)
    public ResponseEntity<ApplicationDto> getById(@PathVariable String id) {
        Application application = applicationRepository.findById(id);
        return new ResponseEntity(application.toDto(), HttpStatus.OK);
    }

    @ApiOperation(value = "application", httpMethod = "POST")
    @RequestMapping(value = "/{id}/approve", method = POST)
    public ResponseEntity approveById(@PathVariable String id, @RequestBody UpdateApplicationRequest request) {

        if (!request.isValid()) {
            return new ResponseEntity(HttpStatus.BAD_REQUEST);
        }

        if (renterRepository.findByAppKey(request.getAppKey()).size() > 0) {
            return new ResponseEntity(HttpStatus.FORBIDDEN);
        }

        Application application = applicationRepository.findOne(id);

        Renter renter = new Renter();
        renter.setAppKey(request.getAppKey());
        renter.setAppName(application.getAppName());
        renter.setAppSecret(UUID.randomUUID().toString());

        application.setStatus(ApplicationStatus.APPROVED.getValue());
        application.setRenter(renter);
        applicationRepository.save(application);
        notificationService.send(EmailTemplateType.ApplicationApproved, application);
        return new ResponseEntity(HttpStatus.CREATED);
    }

    @ApiOperation(value = "application", httpMethod = "POST")
    @RequestMapping(value = "/{id}/reject", method = POST)
    public ResponseEntity rejectById(@PathVariable String id) {
        Application application = applicationRepository.findOne(id);
        application.setStatus(ApplicationStatus.REJECT.value);
        applicationRepository.save(application);
        notificationService.send(EmailTemplateType.ApplicationRejected, application);
        return new ResponseEntity(HttpStatus.OK);
    }

    enum ApplicationStatus {
        REJECT(-1), PENDDING(0), APPROVED(1);

        ApplicationStatus(int value) {
            this.value = value;
        }

        private int value;

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }
    }
}
